/**
* Represents a User of the application
*/
class User { 
    String name
	String displayName
    String password
	String encryptedPassword
    String email
    Date joinedOn = new Date()

    static hasMany = [ideas:SoftwareIdea,votes:Vote,comments:Comment]
                      
	static constraints = {
    	name(size:4..50, blank:false, unique:true)
    	password(size:6..15, blank:false)
    	email(email:true, blank:false, unique:true)    	    	
    }

	//The validation of transient fields does not work as of Grails 0.6
	//Need to figure out the way to validate the password length before the encryption
	//so we don't require an 'encryptedPassword' field
	static transients = ['password']
	
	def voteFor(theIdea) {
		return castVote(theIdea, Vote.POSITIVE_VALUE)
	}
	
	def voteAgainst(theIdea) {
		return castVote(theIdea, Vote.NEGATIVE_VALUE)
	}
	
	//TODO: need to add tests for the voting functionality
	private def castVote(theIdea, value) {
		//Users cannot vote on their own ideas
		if(this.id == theIdea.byUser.id) {
			return false
		}
		def vote = votes.find { it.forIdea.id == theIdea.id }
		//User already has voted on this idea
		if(vote) {
			//Users cannot vote repeatedly with the same value
			if(vote.value == value) {
				return false
			}
			//However,users can change their choice as many times as they like
			else {
				doVoteWithValue(vote, value)
				return true
			}
		}
		//New vote for this idea by user: create it and persist it along with all the associations!
		else {
			vote = new Vote()
			doVoteWithValue(vote, value)
			theIdea.addToVotes(vote)
			this.addToVotes(vote)
			save()
		}
		return true
	}
	
	private def doVoteWithValue(vote, value) {
		if(value == Vote.POSITIVE_VALUE) {
			vote.up()
		}
		else {
			vote.down()
		}
	}
}	
